package edu.cs.usask.ca.silver.plugin.rcp.dialogs.database;

import org.apache.log4j.Logger;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.exceptions.UnableToInitializeStorageException;
import edu.cs.usask.ca.silver.plugin.rcp.components.SilverPreferenceEntries;
import edu.cs.usask.ca.silver.plugin.rcp.dao.SilverBusinessLogicController;

public class SpecifyNewDatabaseConnectionDialog extends TitleAreaDialog {

	private static Logger logger = Logger
			.getLogger(SpecifyNewDatabaseConnectionDialog.class);
	private Text databaseLocationText;
	private Text databaseNameText;
	private Text databasePortText;
	private Text databaseUserText;
	private Text databasePasswordText;
	private String databaseLocation;
	private String databaseName;
	private String databasePort;
	private String databaseUser;
	private String databasePassword;
	private StorageI databaseInstance;

	public SpecifyNewDatabaseConnectionDialog(Shell parentShell) {
		super(parentShell);
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Select From ProjectTree");
	}

	@Override
	public void create() {
		super.create();
		setTitle("Specify Database Connection");
		setMessage("Set up a new Database Connection",
				IMessageProvider.INFORMATION);
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		// layout.horizontalAlignment = GridData.FILL;
		parent.setLayout(layout);

		Group group = new Group(parent, SWT.NONE);
		GridData gridData = new GridData();
		gridData.horizontalIndent = 2;
		gridData.horizontalSpan = 2;
		gridData.verticalSpan = 3;
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = GridData.FILL;
		gridData.verticalAlignment = GridData.FILL;
		group.setLayoutData(gridData);
		group.setLayout(new GridLayout(2, false));

		// The text fields will grow with the size of the dialog
		gridData = new GridData();
		Label label1 = new Label(group, SWT.NONE);
		label1.setText("Database Location");
		label1.setLayoutData(gridData);

		gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		databaseLocationText = new Text(group, SWT.BORDER);
		databaseLocationText.setLayoutData(gridData);

		// database name
		gridData = new GridData();
		Label label2 = new Label(group, SWT.NONE);
		label2.setText("Database Name");
		label2.setLayoutData(gridData);

		gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		databaseNameText = new Text(group, SWT.BORDER);
		databaseNameText.setLayoutData(gridData);

		// database port
		gridData = new GridData();
		Label label3 = new Label(group, SWT.NONE);
		label3.setText("Database Port");
		label3.setLayoutData(gridData);

		gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		databasePortText = new Text(group, SWT.BORDER);
		databasePortText.setLayoutData(gridData);

		// database user
		gridData = new GridData();
		Label label4 = new Label(group, SWT.NONE);
		label4.setText("Login");
		label4.setLayoutData(gridData);

		gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		databaseUserText = new Text(group, SWT.BORDER);
		databaseUserText.setLayoutData(gridData);

		// database pass
		gridData = new GridData();
		Label label5 = new Label(group, SWT.NONE);
		label5.setText("Pass");
		label5.setLayoutData(gridData);

		gridData = new GridData();
		gridData.grabExcessHorizontalSpace = true;
		gridData.horizontalAlignment = SWT.FILL;
		gridData.grabExcessVerticalSpace = true;
		databasePasswordText = new Text(group, SWT.BORDER);
		databasePasswordText.setLayoutData(gridData);

		databaseLocationText.setText(SilverBusinessLogicController
				.getPreferenceEntry(SilverPreferenceEntries.DATABASE_LOCATION));
		databaseNameText.setText(SilverBusinessLogicController
				.getPreferenceEntry(SilverPreferenceEntries.DATABASE_NAME));
		databasePasswordText.setText(SilverBusinessLogicController
				.getPreferenceEntry(SilverPreferenceEntries.DATABASE_PASSWORD));
		databasePortText.setText(SilverBusinessLogicController
				.getPreferenceEntry(SilverPreferenceEntries.DATABASE_PORT));
		databaseUserText.setText(SilverBusinessLogicController
				.getPreferenceEntry(SilverPreferenceEntries.DATABASE_USER));

		return parent;

	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		GridData gridData = new GridData();
		gridData.verticalAlignment = GridData.FILL;
		gridData.horizontalSpan = 3;
		gridData.grabExcessHorizontalSpace = true;
		gridData.grabExcessVerticalSpace = true;
		gridData.horizontalAlignment = SWT.CENTER;

		parent.setLayoutData(gridData);
		// Create Add button
		// Own method as we need to overview the SelectionAdapter
		createOkButton(parent, OK, "Add", true);
		// Add a SelectionListener

		// Create Cancel button
		Button cancelButton = createButton(parent, CANCEL, "Cancel", false);
		// Add a SelectionListener
		cancelButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				setReturnCode(CANCEL);
				close();
			}
		});
	}

	protected Button createOkButton(Composite parent, int id, String label,
			boolean defaultButton) {
		// increment the number of columns in the button bar
		((GridLayout) parent.getLayout()).numColumns++;
		Button button = new Button(parent, SWT.PUSH);
		button.setText(label);
		button.setFont(JFaceResources.getDialogFont());
		button.setData(Integer.valueOf(id));
		button.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				okPressed();
			}
		});
		if (defaultButton) {
			Shell shell = parent.getShell();
			if (shell != null) {
				shell.setDefaultButton(button);
			}
		}
		setButtonLayoutData(button);
		return button;
	}

	private boolean isValidInput() {
		saveInput();
		boolean valid = true;
		if (databaseNameText.getText().length() == 0) {
			setErrorMessage("Please specify database name");
			valid = false;
		}
		if (databaseLocationText.getText().length() == 0) {
			setErrorMessage("Please specify database location");
			valid = false;
		}

		if (databasePasswordText.getText().length() == 0) {
			setErrorMessage("Please specify database password");
			valid = false;
		}

		if (databasePortText.getText().length() == 0) {
			setErrorMessage("Please specify a database port");
			valid = false;
		}

		if (databaseUserText.getText().length() == 0) {
			setErrorMessage("Please specify the login user");
			valid = false;
		}

		if (!testToCreateConnection()) {
			setErrorMessage("Unable to connect to database");
			valid = false;
		}

		return valid;
	}

	private boolean testToCreateConnection() {
		boolean result = true;

		try {
			databaseInstance = SilverBusinessLogicController
					.getRemoteDerbyStorage(databaseLocation, databaseName,
							Integer.valueOf(databasePort), databaseUser,
							databasePassword);

		} catch (UnableToInitializeStorageException ite) {
			result = false;
			MessageDialog
					.openError(
							getParentShell(),
							"Unable to connect to database",
							"Failed to establish connection to database.\n It is possible that you do not have an active internet connection, or the database server is not properly configured.");
			logger.error(
					"Unable to connect to remote database while specifying remote database connection",
					ite);
		}

		return result;
	}

	// We allow the user to resize this dialog
	@Override
	protected boolean isResizable() {
		return true;
	}

	// We need to have the textFields into Strings because the UI gets disposed
	// and the Text Fields are not accessible any more.
	private void saveInput() {
		databaseName = databaseNameText.getText();
		databaseLocation = databaseLocationText.getText();
		databasePassword = databasePasswordText.getText();
		databasePort = databasePortText.getText();
		databaseUser = databaseUserText.getText();
	}

	@Override
	protected void okPressed() {
		if (isValidInput())
			super.okPressed();
	}

	public String getDatabaseName() {
		return databaseName;
	}

	public String getDatabaseLocation() {
		return databaseLocation;
	}

	public String getDatabasePass() {
		return databasePassword;
	}

	public String getDatabaseUser() {
		return databaseUser;
	}

	public String getDatabasePort() {
		return databasePort;
	}

	public StorageI getDatabaseInstance() {
		return databaseInstance;
	}
}
